#include <muduo/net/TcpClient.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/TcpConnection.h>
#include <muduo/net/Buffer.h>
#include <muduo/net/EventLoopThread.h>
#include <iostream>
#include <functional>
#include <unordered_map>
#include "Log.hpp"

using namespace LogMudule;

class DictClient
{
public:
    //初始化
    DictClient(std::string ip, uint16_t port)
        : _loop(_loopt.startLoop()),
          _client(_loop, muduo::net::InetAddress(ip, port), "dictclient"),
          _cdl(1),
          _is_wait(true)
    {
        _client.setConnectionCallback(std::bind(&DictClient::onConnection, this, std::placeholders::_1));
        _client.setMessageCallback(std::bind(&DictClient::onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    }


    //建立连接
    void Connect()
    {
        _client.connect();

        //这里是进行异步操作，防止没连接成功就进行读写，需要等待，直到连接完成被唤醒
        if (_is_wait)
            _cdl.wait();
    }


    //发送数据
    void Send(const std::string &in)
    {
        if (_conn)
        {
            _conn->send(in);
        }
        else
        {
            LOG(LogLevel::ERROR) << "Not connected to server";
        }
    }
    
    ~DictClient()
    {
        //断开连接
        _client.disconnect();
    }

private:
    //作为回调函数 当建立连接时会触发
    void onConnection(const muduo::net::TcpConnectionPtr &conn)
    {
        if (conn->connected())
        {
            _conn = conn;
            if (_is_wait)
            {
                _cdl.countDown();
            }
            LOG(LogLevel::DEBUG) << "连接成功";
        }
        else
        {
            LOG(LogLevel::ERROR) << "连接失败";
        }
    }

    //作为回调函数，当数据准备就绪时会触发
    void onMessage(const muduo::net::TcpConnectionPtr &conn, muduo::net::Buffer *buf, muduo::Timestamp t)
    {
        std::string out = buf->retrieveAllAsString();
        if (!out.empty() && out.back() == '\n')
        {
            out.pop_back();
        }

        std::cout << out << std::endl;
    }

private:
    bool _is_wait;  //是否进行等待
    muduo::net::TcpConnectionPtr _conn; 
    //注意_loopt 要在 _loop先  _loop 要在_client先
    muduo::net::EventLoopThread _loopt; //线程
    muduo::net::EventLoop* _loop;   //循环进行判断
    muduo::net::TcpClient _client;  //tcp客户端
    muduo::CountDownLatch _cdl; ////条件变量
   
};

int main()
{
    DictClient dc("127.0.0.1", 9090);

    std::cout << "----" << std::endl;
    dc.Connect();
    std::cout << "----" << std::endl;

    while (true)
    {
        std::string msg;
        std::cout << "请输入：";
        std::cout.flush();
        std::cin >> msg;

        if (msg == "exit")
        {
            break;
        }

        dc.Send(msg);
    }

    return 0;
}